
package com.hlkj.pay.app.merchant.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.Valid;

import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.common.util.id.IdUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.IAcctAccountAppService;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.common.MerchantResultCode;
import com.hlkj.pay.common.OpenApiResultCode;
import com.hlkj.pay.dto.fund.FundConfigQueryDto;
import com.hlkj.pay.dto.merchant.fund.MerchantFundAccountBindDto;
import com.hlkj.pay.dto.merchant.fund.MerchantFundAccountDto;
import com.hlkj.pay.dto.merchant.fund.ProfitAccountResultDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.gateway.profit.IChannelProfitAccountGateway;
import com.hlkj.pay.infrastructure.model.merchant.*;
import com.hlkj.pay.infrastructure.model.merchant.fund.MerchantFundAccountBindDO;
import com.hlkj.pay.infrastructure.model.merchant.fund.MerchantFundAccountConfigDO;
import com.hlkj.pay.infrastructure.model.merchant.fund.MerchantFundAccountDO;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.merchant.IMerchantFundAccountConfigService;
import com.hlkj.pay.service.merchant.IMerchantFundAccountService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.vo.openapi.fund.req.*;
import com.hlkj.pay.vo.openapi.fund.resp.OpenApiFundAccountResp;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;

/**
 * @author HlpayTeam
 * @date 2025/01/08 16:40
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Validated
public class AcctAccountAppServiceImpl implements IAcctAccountAppService {

    private final IMerchantFundAccountService merchantFundAccountService;

    private final IMerchantApplicationService merchantApplicationService;

    private final IChannelProfitAccountGateway channelProfitAccountGateway;

    private final IMerchantFundAccountConfigService merchantFundAccountConfigService;

    private final IMerchantService merchantService;

    @Override
    public CommonResult<OpenApiFundAccountResp> submitAccount(@Valid OpenApiFundAccountSubmitReq merchantAccessReq) {
        log.info("submitAccount merchantAccessReq:{}", JsonUtils.toJsonString(merchantAccessReq));
        try {
            OpenApiFundAccountInfoReq merchantAccessInfo = merchantAccessReq.getMerchantAccessInfo();
            MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(merchantAccessReq.getMchChannelCode());
            if (merchantAppChannelDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            }
            if (!channelProfitAccountGateway.extensionExist(merchantAppChannelDO.getChannelCode())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_ACCT_ORDER_NOT_EFFECT);
            }
            MerchantFundAccountDto merchantFundAccountDto = new MerchantFundAccountDto();
            // 进件主表信息
            MerchantFundAccountDO merchantFundAccountDO = new MerchantFundAccountDO();
            merchantFundAccountDO.setSn(merchantAppChannelDO.getSn());
            merchantFundAccountDO.setMchChannelCode(merchantAppChannelDO.getCode());
            merchantFundAccountDO.setMchOrderNo(merchantAccessReq.getMchOrderNo());
            merchantFundAccountDO.setType(merchantAccessInfo.getType());
            merchantFundAccountDO.setRemark("");
            merchantFundAccountDto.setMerchantFundAccount(merchantFundAccountDO);
            // 进件营业执照信息
            OpenApiFundAccountLicenseReq merchantAccessLicense = merchantAccessInfo.getMerchantAccessLicense();
            // 进件法人信息
            MerchantCertInfoDO merchantAccessLegalDO = BeanUtil.copy(merchantAccessInfo.getMerchantAccessLegal(), MerchantCertInfoDO.class);
            merchantAccessLegalDO.setOtherValue(merchantAccessInfo.getMerchantAccessLegal().getEmail());
            if (merchantAccessLicense != null) {
                MerchantLicenseDO merchantAccessLicenseDO = BeanUtil.copy(merchantAccessLicense, MerchantLicenseDO.class);
                merchantFundAccountDto.setMerchantFundLicense(merchantAccessLicenseDO);
                merchantFundAccountDO.setName(merchantAccessLicenseDO.getName());
            }
            else {
                merchantFundAccountDO.setName(merchantAccessLegalDO.getName());
            }
            merchantFundAccountDto.setMerchantFundLegal(merchantAccessLegalDO);

            // 联系人信息
            MerchantCertInfoDO merchantAccessContactDO = BeanUtil.copy(merchantAccessInfo.getMerchantAccessContact(), MerchantCertInfoDO.class);
            merchantAccessContactDO.setOtherValue(merchantAccessInfo.getMerchantAccessContact().getEmail());
            merchantFundAccountDto.setMerchantFundContact(merchantAccessContactDO);
            // 进件结算卡信息
            MerchantCardDO merchantAccessCardDO = BeanUtil.copy(merchantAccessReq.getMerchantAccessCard(), MerchantCardDO.class);
            merchantFundAccountDto.setMerchantFundCard(merchantAccessCardDO);
            merchantFundAccountDO.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
            merchantFundAccountDO.setRemark("");
            merchantFundAccountDO.setRequestId(IdUtils.getSnowflakeNextIdStr());
            CommonResult<ProfitAccountResultDto> commonResult = channelProfitAccountGateway.submitProfitAccount(merchantFundAccountDto);
            if (!commonResult.isSuccess()) {
                return CommonResult.error(OpenApiResultCode.CHANNEL_OPERATION_NOT_EXIST.getCode(), commonResult.getMsg());
            }
            merchantFundAccountDO.setAccountNo(commonResult.getData().getAccountNo());
            merchantFundAccountDO.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
            merchantFundAccountService.saveFund(merchantFundAccountDto);
            OpenApiFundAccountResp openApiFundAccountResp = new OpenApiFundAccountResp();
            openApiFundAccountResp.setMchChannelCode(merchantFundAccountDO.getMchChannelCode());
            openApiFundAccountResp.setMchOrderNo(merchantFundAccountDO.getMchOrderNo());
            openApiFundAccountResp.setAccountNo(merchantFundAccountDO.getAccountNo());
            openApiFundAccountResp.setMessage(merchantFundAccountDO.getRemark());
            return CommonResult.success(openApiFundAccountResp);
        }
        catch (Exception e) {
            log.error("submitAccount error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<OpenApiFundAccountResp> updateAccountCard(OpenApiFundAccountUpdateReq fundAccountReq) {
        log.info("submitAccount merchantAccessReq:{}", JsonUtils.toJsonString(fundAccountReq));
        try {
            MerchantFundAccountDto merchantFundAccountDto = merchantFundAccountService.queryAccountByMchOrderNo(fundAccountReq.getMchOrderNo());
            if (merchantFundAccountDto == null) {
                return CommonResult.error(OpenApiResultCode.DATA_NOT_EXIST);
            }
            // 进件结算卡信息
            MerchantCardDO merchantCard = BeanUtil.copy(fundAccountReq.getMerchantAccessCard(), MerchantCardDO.class);
            merchantFundAccountDto.setOldMerchantFundCard(merchantFundAccountDto.getMerchantFundCard());
            merchantFundAccountDto.setMerchantFundCard(merchantCard);
            CommonResult<ProfitAccountResultDto> commonResult = channelProfitAccountGateway.updateProfitAccount(merchantFundAccountDto);
            if (!commonResult.isSuccess()) {
                return CommonResult.error(OpenApiResultCode.CHANNEL_OPERATION_NOT_EXIST.getCode(), commonResult.getMsg());
            }
            merchantFundAccountService.updateFundCard(merchantFundAccountDto);
            MerchantFundAccountDO merchantFundAccount = merchantFundAccountDto.getMerchantFundAccount();
            OpenApiFundAccountResp openApiFundAccountResp = new OpenApiFundAccountResp();
            openApiFundAccountResp.setMchChannelCode(merchantFundAccount.getMchChannelCode());
            openApiFundAccountResp.setMchOrderNo(merchantFundAccount.getMchOrderNo());
            openApiFundAccountResp.setAccountNo(merchantFundAccount.getAccountNo());
            openApiFundAccountResp.setMessage(merchantFundAccount.getRemark());
            return CommonResult.success(openApiFundAccountResp);
        }
        catch (Exception e) {
            log.error("submitAccount error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> accountBind(OpenApiFundAccountBindReq fundAccountBindReq) {
        log.info("accountBind fundAccountBindReq:{}", JsonUtils.toJsonString(fundAccountBindReq));
        try {
            MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(fundAccountBindReq.getMchChannelCode());
            if (merchantAppChannelDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            }

            // 分账绑定判断分账费率是否必填
            // PayOrderEnums.CHANNEL_FUND_PROCESS_TYPE fundProcessType = PayOrderEnums.CHANNEL_FUND_PROCESS_TYPE.from(merchantAppChannelDO.getChannelCode());
            // if (fundProcessType.isNeedFee() && fundAccountBindReq.getFee() == null) {
            //     log.info(fundProcessType.name()+" 预设默认分账数据存在有效手续费不存在 :{}", JSONUtil.toJsonStr(fundAccountBindReq));
            //     return CommonResult.error(0,fundProcessType.name()+" 分账手续费率必填");
            // }

            MerchantFundAccountBindDO merchantFundAccountBindDO = merchantFundAccountService.queryAccountBind(fundAccountBindReq.getMchChannelCode(),
                    fundAccountBindReq.getAccountNo());
            if (merchantFundAccountBindDO != null && CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantFundAccountBindDO.getStatus())) {
                if (fundAccountBindReq.getRate() != null) {
                    List<MerchantFundAccountBindDO> merchantFundAccountBindList = merchantFundAccountService.queryAccountBindList(merchantFundAccountBindDO.getMchChannelCode());
                    if (CollectionUtils.isNotEmpty(merchantFundAccountBindList)) {
                        List<MerchantFundAccountBindDO> collect = merchantFundAccountBindList.stream()
                                .filter(merchantFundAccountBind -> merchantFundAccountBindDO.getId() != merchantFundAccountBind.getId()
                                        && (merchantFundAccountBindDO.getFundProcessType().equals(merchantFundAccountBind.getFundProcessType())
                                                && CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantFundAccountBind.getStatus())))
                                .collect(Collectors.toList());
                        double rateSum = collect.stream().filter(merchantFundAccountBind -> merchantFundAccountBind.getRate() != null)
                                .mapToDouble(merchantFundAccountBind -> merchantFundAccountBind.getRate().doubleValue()).sum();
                        double feeSum = collect.stream().filter(merchantFundAccountBind -> merchantFundAccountBind.getFee() != null)
                                .mapToDouble(merchantFundAccountBind -> merchantFundAccountBind.getFee().doubleValue()).sum();
                        if (new BigDecimal(rateSum).add(fundAccountBindReq.getRate()).compareTo(new BigDecimal(100)) > 0) {
                            return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_RATE_ERROR);
                        }
                        if (fundAccountBindReq.getFee() != null) {
                            if (new BigDecimal(feeSum).add(fundAccountBindReq.getFee()).compareTo(new BigDecimal(100)) > 0) {
                                return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_FEE_ERROR);
                            }
                        }
                    }
                }
                merchantFundAccountBindDO.setD0(fundAccountBindReq.getD0());
                merchantFundAccountBindDO.setFee(fundAccountBindReq.getFee());
                merchantFundAccountBindDO.setRate(fundAccountBindReq.getRate());
                merchantFundAccountBindDO.setSnVisible(fundAccountBindReq.getSnVisible());
                merchantFundAccountService.updateAccountBind(merchantFundAccountBindDO);
                return CommonResult.success();
            }
            MerchantFundAccountBindDO fundAccountBindDO = new MerchantFundAccountBindDO();
            fundAccountBindDO.setAccountNo(fundAccountBindReq.getAccountNo());
            fundAccountBindDO.setMchChannelCode(fundAccountBindReq.getMchChannelCode());
            fundAccountBindDO.setName(fundAccountBindReq.getName());
            fundAccountBindDO.setSnVisible(fundAccountBindReq.getSnVisible());
            fundAccountBindDO.setD0(fundAccountBindReq.getD0());

            // 默认分账
            if(fundAccountBindReq.getFundProcessType() != null &&  fundAccountBindReq.getFundProcessType() == 1){
                fundAccountBindDO.setFundProcessType(1);
                fundAccountBindDO.setStatus(1);
            }

            MerchantFundAccountBindDto merchantFundAccountBindDto = new MerchantFundAccountBindDto();
            merchantFundAccountBindDto.setMerchantFundAccountBindDO(fundAccountBindDO);
            merchantFundAccountBindDto.setMerchantAppChannelDO(merchantAppChannelDO);
            if (channelProfitAccountGateway.extensionExist(merchantAppChannelDO.getChannelCode())) {
                CommonResult<ProfitAccountResultDto> commonResult = channelProfitAccountGateway.bindProfitAccount(merchantFundAccountBindDto);
                if (!commonResult.isSuccess()) {
                    return CommonResult.error(OpenApiResultCode.CHANNEL_OPERATION_NOT_EXIST.getCode(), commonResult.getMsg());
                }
            }
            if (merchantFundAccountBindDO == null) {
                fundAccountBindDO.setFee(fundAccountBindReq.getFee());
                fundAccountBindDO.setRate(fundAccountBindReq.getRate());
                merchantFundAccountService.addAccountBind(fundAccountBindDO);
            }
            else {
                fundAccountBindDO.setFee(fundAccountBindReq.getFee());
                fundAccountBindDO.setRate(fundAccountBindReq.getRate());
                merchantFundAccountService.updateAccountBind(merchantFundAccountBindDO);
            }
            return CommonResult.success();
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("accountBind error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public PageResult<MerchantFundAccountConfigDO> accountConfigPage(FundConfigQueryDto fundQueryDto) {
        return merchantFundAccountConfigService.queryPage(fundQueryDto);
    }

    @Override
    public MerchantFundAccountConfigDO accountConfigSelectOne(FundConfigQueryDto fundQueryDto) {
        List<MerchantFundAccountConfigDO> list = merchantFundAccountConfigService.queryList(fundQueryDto);
        if(CollUtil.isNotEmpty(list) && list.size() == 1){
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<MerchantFundAccountConfigDO> accountConfigList(FundConfigQueryDto fundQueryDto) {
        return merchantFundAccountConfigService.queryList(fundQueryDto);
    }

    @Override
    public CommonResult<Void> accountConfigAdd(OpenApiFundAccountConfigReq fundAccountConfigReq) {
        log.info("accountConfigAdd fundAccountConfigReq:{}", JsonUtils.toJsonString(fundAccountConfigReq));
        try {
            MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(fundAccountConfigReq.getSn());
            if (merchantInfoDO == null) {
                return CommonResult.error(MerchantResultCode.MERCHANT_NOT_EXIST);
            }
            if(fundAccountConfigReq.getType() == null){
                return CommonResult.error(0,"分账类型");
            }
            // // 重复判断
            // FundConfigQueryDto fundConfigQueryDto = new FundConfigQueryDto();
            // fundConfigQueryDto.setType(fundAccountConfigReq.getType());
            // // 分账类型 1：服务商渠道 2：商户服务商渠道
            // MerchantEnum.FUND_TYPE fundType = MerchantEnum.FUND_TYPE.from(fundAccountConfigReq.getType());
            // switch (fundType){
            //     case P_CHANNEL:
            //         fundConfigQueryDto.setProviderCode(fundAccountConfigReq.getProviderCode());
            //         fundConfigQueryDto.setChannelCode(fundAccountConfigReq.getChannelCode());
            //         break;
            //     case SP_CHANNEL:
            //         fundConfigQueryDto.setSn(fundAccountConfigReq.getSn());
            //         fundConfigQueryDto.setProviderCode(fundAccountConfigReq.getProviderCode());
            //         fundConfigQueryDto.setChannelCode(fundAccountConfigReq.getChannelCode());
            //         break;
            // }
            // List<MerchantFundAccountConfigDO> list = merchantFundAccountConfigService.queryList(fundConfigQueryDto);
            // if(CollUtil.isNotEmpty(list)){
            //     return CommonResult.error(0,"分账配置不可重复");
            // }
            MerchantFundAccountConfigDO fundAccountConfigDO = BeanUtil.copy(fundAccountConfigReq,MerchantFundAccountConfigDO.class);
            merchantFundAccountConfigService.addConfig(fundAccountConfigDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("accountConfigAdd error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> accountConfigUpdate(OpenApiFundAccountConfigReq fundAccountConfigReq) {
        log.info("accountConfigUpdate fundAccountConfigReq:{}", JsonUtils.toJsonString(fundAccountConfigReq));
        try {
            MerchantFundAccountConfigDO old = merchantFundAccountConfigService.detail(fundAccountConfigReq.getId());
            if(old == null){
                return CommonResult.error(0,"数据不存在");
            }

            MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(old.getSn());
            if (merchantInfoDO == null) {
                return CommonResult.error(MerchantResultCode.MERCHANT_NOT_EXIST);
            }
            MerchantFundAccountConfigDO fundAccountConfigDO = BeanUtil.copy(fundAccountConfigReq,MerchantFundAccountConfigDO.class);
            fundAccountConfigDO.setId(old.getId());
            merchantFundAccountConfigService.updateConfig(fundAccountConfigDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("accountConfigUpdate error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<MerchantFundAccountConfigDO> accountConfigDetail(Long id) {
        MerchantFundAccountConfigDO configDO = merchantFundAccountConfigService.detail(id);
        return CommonResult.success(configDO);
    }

    @Override
    public CommonResult<Void> accountConfigDelete(Long id) {
        merchantFundAccountConfigService.delConfig(id);
        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> accountUnBind(OpenApiFundAccountBindReq accountBindReq) {
        log.info("accountUnBind fundAccountBindReq:{}", JsonUtils.toJsonString(accountBindReq));
        try {
            MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(accountBindReq.getMchChannelCode());
            if (merchantAppChannelDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            }
            MerchantFundAccountBindDO merchantFundAccountBindDO = merchantFundAccountService.queryAccountBind(accountBindReq.getMchChannelCode(), accountBindReq.getAccountNo());
            if (merchantFundAccountBindDO == null) {
                return CommonResult.error(OpenApiResultCode.DATA_NOT_EXIST);
            }
            MerchantFundAccountBindDto merchantFundAccountBindDto = new MerchantFundAccountBindDto();
            merchantFundAccountBindDto.setMerchantFundAccountBindDO(merchantFundAccountBindDO);
            merchantFundAccountBindDto.setMerchantAppChannelDO(merchantAppChannelDO);
            if (channelProfitAccountGateway.extensionExist(merchantAppChannelDO.getChannelCode())) {
                CommonResult<ProfitAccountResultDto> commonResult = channelProfitAccountGateway.unBindProfitAccount(merchantFundAccountBindDto);
                if (!commonResult.isSuccess()) {
                    return CommonResult.error(OpenApiResultCode.CHANNEL_OPERATION_NOT_EXIST.getCode(), commonResult.getMsg());
                }
            }
            merchantFundAccountService.delAccountBind(merchantFundAccountBindDO.getId());
            return CommonResult.success();
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("accountUnBind error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<OpenApiFundAccountSubmitReq> queryAccountById(Long id) {
        log.info("submitAccount id:{}", id);
        try {
            MerchantFundAccountDto merchantFundAccountDto = merchantFundAccountService.queryAccountDetail(id);
            if (merchantFundAccountDto == null) {
                return null;
            }
            OpenApiFundAccountSubmitReq openApiFundAccountSubmitReq = new OpenApiFundAccountSubmitReq();
            openApiFundAccountSubmitReq.setMchChannelCode(openApiFundAccountSubmitReq.getMchChannelCode());
            openApiFundAccountSubmitReq.setMchOrderNo(openApiFundAccountSubmitReq.getMchOrderNo());
            if (merchantFundAccountDto.getMerchantFundCard() != null) {
                openApiFundAccountSubmitReq.setMerchantAccessCard(BeanUtil.copy(merchantFundAccountDto.getMerchantFundCard(), OpenApiFundAccountCardReq.class));
            }
            OpenApiFundAccountInfoReq openApiFundAccountInfoReq = new OpenApiFundAccountInfoReq();
            openApiFundAccountSubmitReq.setMerchantAccessInfo(openApiFundAccountInfoReq);
            openApiFundAccountInfoReq.setType(merchantFundAccountDto.getMerchantFundAccount().getType());
            MerchantLicenseDO merchantFundLicense = merchantFundAccountDto.getMerchantFundLicense();
            if (merchantFundLicense != null) {
                openApiFundAccountInfoReq.setMerchantAccessLicense(BeanUtil.copy(merchantFundLicense, OpenApiFundAccountLicenseReq.class));
            }
            MerchantCertInfoDO merchantFundLegal = merchantFundAccountDto.getMerchantFundLegal();
            if (merchantFundLegal != null) {
                OpenApiFundAccountCertReq fundAccountCertReq = BeanUtil.copy(merchantFundLegal, OpenApiFundAccountCertReq.class);
                fundAccountCertReq.setEmail(merchantFundLegal.getOtherValue());
                openApiFundAccountInfoReq.setMerchantAccessLegal(fundAccountCertReq);
            }
            MerchantCertInfoDO merchantFundContact = merchantFundAccountDto.getMerchantFundContact();
            if (merchantFundContact != null) {
                OpenApiFundAccountContactReq fundAccountCertReq = BeanUtil.copy(merchantFundContact, OpenApiFundAccountContactReq.class);
                fundAccountCertReq.setEmail(merchantFundContact.getOtherValue());
                openApiFundAccountInfoReq.setMerchantAccessContact(fundAccountCertReq);
            }
            MerchantAppChannelDO merchantAppChannelDO = merchantApplicationService.queryAppChannelDetail(merchantFundAccountDto.getMerchantFundAccount().getMchChannelCode());
            openApiFundAccountSubmitReq.setChannelCode(merchantAppChannelDO.getChannelCode());
            openApiFundAccountSubmitReq.setProviderCode(merchantAppChannelDO.getProviderCode());
            return CommonResult.success(openApiFundAccountSubmitReq);
        }
        catch (Exception e) {
            log.error("queryAccountById error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public void queryAccountBindList(String mchChannelCode) {
        channelProfitAccountGateway.queryAccountBindList(mchChannelCode);
    }

    @Override
    public CommonResult<Void> updateStatus(OpenApiFundAccountBindStatusReq openApiFundAccountBindStatusReq) {
        log.info("updateStatus openApiFundAccountBindStatusReq:{}", JsonUtils.toJsonString(openApiFundAccountBindStatusReq));
        try {
            MerchantFundAccountBindDO merchantFundAccountBindDO = merchantFundAccountService.queryAccountBind(openApiFundAccountBindStatusReq.getMchChannelCode(),
                    openApiFundAccountBindStatusReq.getAccountNo());
            if (merchantFundAccountBindDO == null) {
                return CommonResult.error(OpenApiResultCode.DATA_NOT_EXIST);
            }
            if (openApiFundAccountBindStatusReq.getStatus().equals(merchantFundAccountBindDO.getStatus())) {
                return CommonResult.success();
            }
            if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(openApiFundAccountBindStatusReq.getStatus())) {
                if (merchantFundAccountBindDO.getFundProcessType() == null) {
                    return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_FUND_PROCESS_TYPE_NULL);
                }
                // if (merchantFundAccountBindDO.getRate() == null) {
                // return
                // CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_FUND_PROCESS_TYPE_NULL);
                // }
                if (merchantFundAccountBindDO.getRate() != null) {
                    List<MerchantFundAccountBindDO> merchantFundAccountBindList = merchantFundAccountService.queryAccountBindList(merchantFundAccountBindDO.getMchChannelCode());
                    if (CollectionUtils.isNotEmpty(merchantFundAccountBindList)) {
                        List<MerchantFundAccountBindDO> collect = merchantFundAccountBindList.stream()
                                .filter(merchantFundAccountBind -> (merchantFundAccountBindDO.getFundProcessType() != null
                                        && merchantFundAccountBindDO.getFundProcessType().equals(merchantFundAccountBind.getFundProcessType())
                                        && CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantFundAccountBind.getStatus())))
                                .collect(Collectors.toList());
                        collect.add(merchantFundAccountBindDO);
                        double rateSum = collect.stream().filter(merchantFundAccountBind -> merchantFundAccountBind.getRate() != null)
                                .mapToDouble(merchantFundAccountBind -> merchantFundAccountBind.getRate().doubleValue()).sum();
                        double feeSum = collect.stream().filter(merchantFundAccountBind -> merchantFundAccountBind.getFee() != null)
                                .mapToDouble(merchantFundAccountBind -> merchantFundAccountBind.getFee().doubleValue()).sum();
                        if (new BigDecimal(rateSum).compareTo(new BigDecimal(100)) > 0) {
                            return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_RATE_ERROR);
                        }
                        if (new BigDecimal(feeSum).compareTo(new BigDecimal(100)) > 0) {
                            return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_FEE_ERROR);
                        }
                    }
                }
            }
            MerchantFundAccountBindDO merchantFundAccount = new MerchantFundAccountBindDO();
            merchantFundAccount.setId(merchantFundAccountBindDO.getId());
            merchantFundAccount.setStatus(openApiFundAccountBindStatusReq.getStatus());
            merchantFundAccountService.updateAccountBind(merchantFundAccount);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateStatus error:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> updateBindType(OpenApiFundAccountBindTypeReq openApiFundAccountBindTypeReq) {
        log.info("updateBindType openApiFundAccountBindTypeReq:{}", JsonUtils.toJsonString(openApiFundAccountBindTypeReq));
        try {
            MerchantFundAccountBindDO merchantFundAccountBindDO = merchantFundAccountService.queryAccountBind(openApiFundAccountBindTypeReq.getMchChannelCode(),
                    openApiFundAccountBindTypeReq.getAccountNo());
            if (merchantFundAccountBindDO == null) {
                return CommonResult.error(OpenApiResultCode.DATA_NOT_EXIST);
            }
            if (openApiFundAccountBindTypeReq.getFundProcessType().equals(merchantFundAccountBindDO.getFundProcessType())) {
                return CommonResult.success();
            }
            // if (merchantFundAccountBindDO.getRate() == null) {
            // return
            // CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_FUND_PROCESS_TYPE_NULL);
            // }
            if (merchantFundAccountBindDO.getRate() != null) {
                List<MerchantFundAccountBindDO> merchantFundAccountBindList = merchantFundAccountService.queryAccountBindList(merchantFundAccountBindDO.getMchChannelCode());
                if (CollectionUtils.isNotEmpty(merchantFundAccountBindList)) {
                    List<MerchantFundAccountBindDO> collect = merchantFundAccountBindList.stream()
                            .filter(merchantFundAccountBind -> (merchantFundAccountBindDO.getFundProcessType() != null
                                    && merchantFundAccountBindDO.getFundProcessType().equals(merchantFundAccountBind.getFundProcessType())
                                    && CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantFundAccountBind.getStatus())))
                            .collect(Collectors.toList());
                    collect.add(merchantFundAccountBindDO);
                    double rateSum = collect.stream().filter(merchantFundAccountBind -> merchantFundAccountBind.getRate() != null)
                            .mapToDouble(merchantFundAccountBind -> merchantFundAccountBind.getRate().doubleValue()).sum();
                    double feeSum = collect.stream().filter(merchantFundAccountBind -> merchantFundAccountBind.getFee() != null)
                            .mapToDouble(merchantFundAccountBind -> merchantFundAccountBind.getFee().doubleValue()).sum();
                    if (new BigDecimal(rateSum).compareTo(new BigDecimal(100)) > 0) {
                        return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_RATE_ERROR);
                    }
                    if (new BigDecimal(feeSum).compareTo(new BigDecimal(100)) > 0) {
                        return CommonResult.error(MerchantResultCode.MERCHANT_PROFIT_ACCOUNT_FEE_ERROR);
                    }
                }
            }
            MerchantFundAccountBindDO merchantFundAccount = new MerchantFundAccountBindDO();
            merchantFundAccount.setId(merchantFundAccountBindDO.getId());
            merchantFundAccount.setFundProcessType(openApiFundAccountBindTypeReq.getFundProcessType());
            merchantFundAccountService.updateAccountBind(merchantFundAccount);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateBindType error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }
}
